package com.link.gateway.core.filter.visitstatistics.util;

import com.link.gateway.core.utils.StringUtils;
import org.springframework.http.server.reactive.ServerHttpRequest;

import java.util.Map;

/**
 * 接口访问统计工具类
 *
 * @author LiYang
 * @date 20190826
 */
public class VisitUtil {

    /**
     * 计算单位时间内限制次数
     *
     * @author LiYang
     * @date 20190826
     * @param request
     * @return
     */
    public static String calcuLimitNumByUrl(ServerHttpRequest request) {
        String url = VisitUtil.getUrl(request);
        VisitConfigSingleton configInstance = VisitConfigSingleton.getInstance();
        Map<String, Boolean> noRecordMap = configInstance.getNoRecord();
        if (null != noRecordMap.get(url)) {
            return "N";
        }
        if (StringUtils.isBlank(configInstance.getLoginLimitNum()) && "/base/user/login".equalsIgnoreCase(url)) {
            return configInstance.getLoginLimitNum();
        }
        Map<String, Boolean> specialUrlMap = configInstance.getSpecialUrl();
        if (null != specialUrlMap.get(url) && !StringUtils.isBlank(configInstance.getSpecialLimitNum())) {
            return configInstance.getSpecialLimitNum();
        }
        String redisConfigLimit = configInstance.getLimitVisitNum();
        if (!StringUtils.isBlank(redisConfigLimit)) {
            return redisConfigLimit;
        }
        return "10000";
    }

    /**
     * 计算单位时间
     *
     * @author LiYang
     * @date 20190826
     * @param request
     * @return
     */
    public static String calcuLimitTimeByUrl(ServerHttpRequest request) {
        String url = VisitUtil.getUrl(request);
        VisitConfigSingleton configInstance = VisitConfigSingleton.getInstance();
        Map<String, Boolean> noRecordMap = configInstance.getNoRecord();
        if (null != noRecordMap.get(url)) {
            return "N";
        }
        if (StringUtils.isBlank(configInstance.getLoginLimitTime()) && "/base/user/login".equalsIgnoreCase(url)) {
            return configInstance.getLoginLimitTime();
        }
        Map<String, Boolean> specialUrlMap = configInstance.getSpecialUrl();
        if (null != specialUrlMap.get(url) && !StringUtils.isBlank(configInstance.getSpecialLimitTime())) {
            return configInstance.getSpecialLimitTime();
        }
        String redisConfigLimit = configInstance.getLimitTime();
        if (!StringUtils.isBlank(redisConfigLimit)) {
            return redisConfigLimit;
        }
        return "1";
    }

    /**
     * 生成lua脚本
     *
     * @author LiYang
     * @date 20190826
     * @param expire
     * @return
     */
    public static String getLuaScript(String expire) {
        StringBuilder sb = new StringBuilder();
        sb.append("local key = KEYS[1]\n");
        sb.append("local limit = tonumber(ARGV[1])\n");
        sb.append("local current = tonumber(redis.call('get', key) or \"0\")\n");
        sb.append("if current + 1 > limit then\n");
        sb.append("\treturn 0\n");
        sb.append("else\n");
        sb.append("\tredis.call(\"INCRBY\", key, \"1\")\n");
        sb.append("\tredis.call(\"expire\", key, ");
        sb.append(Integer.parseInt(expire) * 60);
        sb.append(")\n");
        sb.append("\treturn 1\n");
        sb.append("end");
        return sb.toString();
    }

    /**
     * 生成lua脚本
     *
     * @author LiYang
     * @date 20190826
     * @return
     */
    public static String getLuaScript() {
        StringBuilder sb = new StringBuilder();
        sb.append("local key = \"{rate.limit:}\" .. KEYS[1]\n");
        sb.append("local limit = tonumber(ARGV[1])\n");
        sb.append("local expire_time = ARGV[2]\n");
        sb.append("local is_exists = redis.call(\"EXISTS\", key)\n");
        sb.append("if is_exists == 1 then\n");
        sb.append("\tif redis.call(\"INCR\", key) > limit then\n");
        sb.append("\t\treturn 0\n");
        sb.append("\telse\n");
        sb.append("\t\treturn 1\n");
        sb.append("\tend\n");
        sb.append("else\n");
        sb.append("\tredis.call(\"SET\", key, 1)\n");
        sb.append("\tredis.call(\"EXPIRE\", key, expire_time)\n");
        sb.append("\treturn 1\n");
        sb.append("end");
        return sb.toString();
    }

    /**
     * 根据reqeust获得访问的url
     *
     * @author LiYang
     * @date 20190826
     * @param request
     * @return
     */
    public static String getUrl(ServerHttpRequest request) {
        String contextPath = request.getPath().contextPath().value();
        String uri = (request.getURI().getPath().replace(contextPath, ""))
                .replace("/action", "");
        return uri;
    }

    public static void main(String[] args) {
        System.out.println(getLuaScript());
    }
}
